package wave

import (
	"encoding/binary"
	"math"
	"os"
)

// Wave the struct hold wave header and data.
type Wave struct {
	data       [][]int16
	sampleFreq float64
}

// NewWave new a Wave.
func NewWave() *Wave {
	we := Wave{}
	return &we
}

// Read read the fpath wave file to Wave struct.
func (we *Wave) Read(fpath string) {
	const blockSize uint32 = 1024 * 1024
	file, err := os.Open(fpath)
	if err != nil {
		panic(err)
	}
	header := NewHeader()
	header.Read(file)

	we.sampleFreq = header.sampleFreq

	buffer := make([]byte, 0)
	var bytesToGo uint32 = header.DataBytes()
	for bytesToGo > 0 {
		blockBytes := uint32(math.Min(float64(bytesToGo), float64(blockSize)))
		readBytes := make([]byte, int(blockBytes))
		n, _ := file.Read(readBytes)
		buffer = append(buffer, readBytes[:n]...)
		bytesToGo -= uint32(n)
	}

	if len(buffer) == 0 {
		panic("empty wave file")
	}
	we.data = make([][]int16, header.numChannels)
	for i := 0; i < len(we.data); i++ {
		we.data[i] = make([]int16, len(buffer)/int(header.BlockAlign()))
	}
	offset := 0
	for i := 0; i < len(buffer)/int(header.BlockAlign()); i++ {
		for j := 0; j < int(header.numChannels); j++ {
			k := buffer[offset : offset+2]
			offset += 2
			if header.reverseBytes {
				ReverseBytes(k)
			}
			if IsLittleEndian() {
				we.data[j][i] = int16(binary.LittleEndian.Uint16(k))
			} else {
				we.data[j][i] = int16(binary.BigEndian.Uint16(k))
			}
		}
	}

	//TODO:
}

//func (we *Wave) Write(fpath string) {
//	//TODO:
//}
//
//func (we *Wave) CopyFrom(thatW *Wave) {
//	//TODO:
//}
